package com.shujia.day19.mysql.pool;

import java.sql.SQLException;
import java.util.ArrayList;

public class MySqlConnectionPool {
    /*
        TODO Mysql的一个连接池
            1.构造连接池的时候需要初始化多个Mysql连接
            2.构造连接池对象需要传入一个连接池配置类
            3.连接池中对应会有两个集合用于存放Mysql连接
     */
    MysqlPoolConfig mysqlPoolConfig;
    ArrayList<MysqlConnection> notUseCon;
    ArrayList<MysqlConnection> usingCon;

    {
        notUseCon = new ArrayList<>();
        usingCon = new ArrayList<>();
    }

    public MySqlConnectionPool(MysqlPoolConfig mysqlPoolConfig) {
        this.mysqlPoolConfig = mysqlPoolConfig;
        // TODO 根据初始化值创建Mysql连接
        for (int i = 0; i < mysqlPoolConfig.init_con_num; i++) {
            MysqlConnection mysqlConnection = new MysqlConnection(mysqlPoolConfig.mysqlConfig, DateParseUtil.parseTime(System.currentTimeMillis()) + ":" + i);
            System.out.println("正在创建一个Mysql连接"+mysqlConnection.mysqlConName);
            notUseCon.add(mysqlConnection);
        }
    }

    public synchronized MysqlConnection getMysqlCon() {
        /*
            TODO 获取连接：
                从当前未使用的集合中将一个Mysql的连接移动到另外一个集合中
         */
        MysqlConnection connection = null;
        if (notUseCon.size() > 0) {
            connection = notUseCon.remove(0);
            usingCon.add(connection);
            System.out.println("当前线程获取到一个连接:"+connection.mysqlConName+ "正在使用的连接数:" + usingCon.size() + "未使用的连接数:" + notUseCon.size());
        } else {
            /*
               TODO 如果当未使用的集合中，没有可用连接
                    1.如果没有超过最大的连接数量 => 创建新的连接
                    2.如果超过最大连接那么就需要对获取的当前线程进行暂停
             */
            int allCon = notUseCon.size() + usingCon.size();
            if (allCon < mysqlPoolConfig.max_con_num) {
                connection = new MysqlConnection(mysqlPoolConfig.mysqlConfig, DateParseUtil.parseTime(System.currentTimeMillis()) + "新增");
                usingCon.add(connection);
                System.out.println("当前线程获取到了一个Mysql连接" + connection.mysqlConName + "所有连接数：" + allCon + "正在使用的连接数:" + usingCon.size() + "未使用的连接数:" + notUseCon.size());
            } else {
                System.out.println("超过最大连接数的数量，当前连接池中所有连接数：" + allCon + "正在使用的连接数:" + usingCon.size() + "未使用的连接数:" + notUseCon.size());
                System.out.println("当前线程需要等待其他线程释放连接");
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return connection;
    }

    public synchronized boolean releaseMysqlCon(MysqlConnection mysqlConnection) {
        // TODO 释放Mysql连接
        boolean remove = usingCon.remove(mysqlConnection);
        try {
            // 当连接对象没有被关闭，那么可以继续使用
            if (!mysqlConnection.getConnection().isClosed()) {
                notUseCon.add(mysqlConnection);
                // 当前线程回收时候，表示线程处于空闲状态
                mysqlConnection.flagTime = System.currentTimeMillis();
                System.out.println("当前线程回收了一个Mysql连接:"+mysqlConnection.mysqlConName+"未使用的连接数："+notUseCon.size()+"正在使用的连接数:"+usingCon.size());
                System.out.println("尝试唤醒一个正在等待的线程...");
                this.notify();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        return remove;
    }
}
